﻿using System;
using System.ComponentModel;
using System.Net;
using System.Windows;
using System.Windows.Browser;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace DiscoveryLogic.UI.Charts
{
    public abstract class ObservableObject:VisualElement, INotifyPropertyChanged
    {
        #region fields
        internal static Boolean _isPropertyChangedFired = false;
        internal Boolean _isAutoGenerated;
        #endregion

        #region ctor
        public ObservableObject():base()
        {
            this.EventChanged += delegate
                                     {
                                         FirePropertyChanged("MouseEvent");
                                     };
            IsNotificationEnable = true;
        }
        #endregion

        #region props

        public VisualControl Chart { get; set; }
        public override string ToolTipText
        {
            get
            {
                if (Chart != null && !string.IsNullOrEmpty((Chart as Chart).ToolTipText))
                    return null;
                else
                    return (string) GetValue(ToolTipTextProperty);
            }
            set
            {
                SetValue(ToolTipTextProperty,value);
            }
        }

        internal static Boolean IsInDesignMode
        {
            get
            {
                return !HtmlPage.IsEnabled;
            }
        }

        internal Boolean IsNotificationEnable
        {
            get;
            set;
        }
        #endregion

        #region pub methods
        public void ApplyStyleFromTheme(VisualControl control, string keyName)
        {
            bool oldIsNotificationEnable = IsNotificationEnable;
            IsNotificationEnable = false;
            Chart chart = control as Chart;
            if (Style == null)
            {
                if (chart.StyleDictionary != null)
                {
                    Style myStyle = chart.StyleDictionary[keyName] as Style;
                    if (myStyle != null)
                        Style = myStyle;
                }
            }
            IsNotificationEnable = oldIsNotificationEnable;
        }
        #endregion

        #region Protected Methods

        /// <summary>
        /// UpdateVisual is used for partial rendering
        /// </summary>
        /// <param name="propertyName">Name of the property</param>
        /// <param name="value">Value of the property</param>
        internal virtual void UpdateVisual(String propertyName, object value)
        {

        }

        /// <summary>
        /// Check whether the Property value is changed
        /// </summary>
        /// <typeparam name="T">Type</typeparam>
        /// <param name="propertyName">Property Name</param>
        /// <param name="oldValue">Old property value</param>
        /// <param name="newValue">New property value</param>
        /// <returns></returns>
        protected bool CheckPropertyChanged<T>(string propertyName, ref T oldValue, ref T newValue)
        {
            if (oldValue == null && newValue == null)
            {
                return false;
            }

            if ((oldValue == null && newValue != null) || !oldValue.Equals((T)newValue))
            {
                oldValue = newValue;

                FirePropertyChanged(propertyName);

                return true;
            }

            return false;
        }

        /// <summary>
        /// Fire property change event
        /// </summary>
        /// <param name="propertyName">Property Name</param>
        internal void FirePropertyChanged(string propertyName)
        {
            _isPropertyChangedFired = false; // Used for testing

            if (this.PropertyChanged != null && this.IsNotificationEnable)
            {
                if (IsInDesignMode)
                {
                    this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
                }
                else if (Chart != null && (Chart as Chart)._IsTemplateApplied)
                {   
                    if (Application.Current != null && Application.Current.RootVisual != null && Application.Current.RootVisual.Dispatcher != null)
                    {
                        System.Windows.Threading.Dispatcher currentDispatcher = Application.Current.RootVisual.Dispatcher;

                            if (currentDispatcher.CheckAccess())
                                (Chart as Chart).InvokeRender();
                            else
                                currentDispatcher.BeginInvoke(new Action<String>(FirePropertyChanged), propertyName);
                    }
                    else // if we did not get the Dispatcher throw an exception
                    {
                        throw new InvalidOperationException("This object must be initialized after that the RootVisual has been loaded");
                    }

                    _isPropertyChangedFired = true;   // Used for testing
                }
            }
        }

        #endregion

        #region Internal Methods

        /// <summary>
        /// Formats newline character
        /// </summary>
        /// <param name="text">Text</param>
        /// <returns>Formated Text</returns>
        internal static String GetFormattedMultilineText(String text)
        {
            if (String.IsNullOrEmpty(text))
                return "";

            String[] split = { "\\n" };
            String[] lines = text.Split(split, StringSplitOptions.RemoveEmptyEntries);
            String multiLineText = "";
            foreach (String line in lines)
            {
                if (line.EndsWith("\\"))
                {
                    multiLineText += line + "n";
                }
                else
                {
                    multiLineText += line + "\n";
                }
            }

            if (text.EndsWith("\\n"))
                return multiLineText;
            else
                return multiLineText.Substring(0, multiLineText.Length - 1);
        }

        #endregion

        #region Implementation of INotifyPropertyChanged

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion
    }
}
